package org.hdz.pcmdemo;

import android.content.Context;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Handler;
import android.os.Message;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;

/**
 * @author hdz
 * @date 2018/12/1 22:31
 */
public class MyAudioPlay {
    private static final String TAG = "MyAudioPlay";

    private Handler mHandler;
    private WeakReference<Context> mWeakContext = null;

    private AudioParams mAudioParams = null;
    private AudioTrack mAudioTrack = null;
    private PlayThread mPlayThread;
    private String sPcmFilePath = "";

    private int iAudioFileType = 0;
    private boolean bPlaying;

    public MyAudioPlay(Context context, Handler handler, AudioParams params) {
        mHandler = handler;
        mAudioParams = params;
        if (mAudioParams != null) {
            createAudioTrack();
        }
        mWeakContext = new WeakReference<>(context);
    }

    public void release() {
        stop();
        releaseAudioTrack();
    }

    public void play(int type, String filePath) {
        if (bPlaying) {
            return;
        } else {
            bPlaying = true;
        }
        sPcmFilePath = filePath;
        iAudioFileType = type;
        startThread();
    }

    public void stop() {
        bPlaying = false;
        if (mPlayThread != null) {
            mPlayThread.interrupt();
            mPlayThread = null;
        }
    }

    private InputStream getPcmFileStream() {
        if ("".equals(sPcmFilePath)) {
            return null;
        }
        InputStream inStream = null;
        if (1 == iAudioFileType) {
            try {
                inStream = mWeakContext.get().getAssets().open(sPcmFilePath);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            File file = new File(sPcmFilePath);
            if (file.exists()) {
                try {
                    inStream = new FileInputStream(file);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return inStream;
    }

    private void createAudioTrack() {
        // 获得构建对象的最小缓冲区大小
        // 根据音频数据的特性来确定所要分配的缓冲区的最小size
        int minBufSize = AudioTrack.getMinBufferSize(mAudioParams.iFrequency, mAudioParams.iChannel, mAudioParams.iSampBit);

//		         STREAM_ALARM：警告声
//		         STREAM_MUSCI：音乐声，例如music等
//		         STREAM_RING：铃声
//		         STREAM_SYSTEM：系统声音
//		         STREAM_VOCIE_CALL：电话声音
        mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, mAudioParams.iFrequency, mAudioParams.iChannel, mAudioParams.iSampBit, minBufSize, AudioTrack.MODE_STREAM);
//				AudioTrack中有MODE_STATIC和MODE_STREAM两种分类。
//      		STREAM的意思是由用户在应用程序通过write方式把数据一次一次得写到audiotrack中。
//				这个和我们在socket中发送数据一样，应用层从某个地方获取数据，例如通过编解码得到PCM数据，然后write到audiotrack。
//				这种方式的坏处就是总是在JAVA层和Native层交互，效率损失较大。
//				而STATIC的意思是一开始创建的时候，就把音频数据放到一个固定的buffer，然后直接传给audiotrack，
//				后续就不用一次次得write了。AudioTrack会自己播放这个buffer中的数据。
//				这种方法对于铃声等内存占用较小，延时要求较高的声音来说很适用。
    }

    private void releaseAudioTrack() {
        if (mAudioTrack != null){
            mAudioTrack.stop();
            mAudioTrack.release();
            mAudioTrack = null;
        }
    }

    private void startThread() {
        bPlaying = true;
        if (mPlayThread == null) {
            mPlayThread = new PlayThread();
            mPlayThread.start();
        } else {
            mPlayThread = null;
            mPlayThread = new PlayThread();
            mPlayThread.start();
        }
    }


    class PlayThread extends Thread {
        @Override
        public void run() {
            InputStream inputStream = getPcmFileStream();
            if (inputStream == null) {
                Logger.e(TAG+",PlayThread run: inputStream == null " + iAudioFileType);
                return;
            }
            try {
                int size = inputStream.available();
                Logger.d(TAG+",PlayThread run: inputStream size: " + size);
            } catch (IOException e) {
                e.printStackTrace();
            }
            mAudioTrack.play();
            byte[] data = new byte[Constant.PLAY_AUDIO_FRAME_SIZE];
            while(true) {
                if (!bPlaying) {
                    break;
                }
                try {
                    int len = inputStream.read(data, 0, data.length);
                    if (len < 0) {
                        break;
                    }
                    mAudioTrack.write(data, 0, len);
                    if (len < data.length) {
                        break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    break;
                }
            }
            mAudioTrack.stop();
            bPlaying = false;

            //播放完成通知UI
            if (mHandler != null) {
                Message msg = mHandler.obtainMessage(Constant.MSG_ID);
                msg.what = Constant.PLAY_STATE_COMPLETE;
                msg.sendToTarget();
            }
        }
    }
}
